﻿using AppDesign.Models;
using Breeze.ContextProvider;
using Breeze.ContextProvider.EF6;
using Breeze.WebApi2;
using Newtonsoft.Json.Linq;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Web.Http;
using System.Reflection;
using Microsoft.CSharp;
using System.Reflection.Emit;
using System.Collections;
using AppDesign.Models.ManageType;

namespace AppDesign.Controllers
{
    [BreezeController]
    public class DataController : ApiController
    {
        [HttpGet]
        public List<string> GetTypes()
        {
            List<string> Types = new List<string>();
            Assembly assembly = Assembly.LoadFrom("D:\\Projects\\IDTE\\Binary\\Idte.HumanResource.Core.dll");
            foreach (Type type in assembly.GetTypes())
            {
                if(!type.IsGenericType){
                    Types.Add(type.Name);
                }              
            }
            return Types;
        }

        [HttpGet]
        public void GenerateClass()
        {
            //AppDesignContext adc = new AppDesignContext();
            //READ DLL CONTENT ******************************************************
            Assembly assembly = Assembly.LoadFrom("D:\\Projects\\IDTE\\Binary\\Idte.HumanResource.Core.dll");
            //foreach (Type type in assembly.GetTypes())
            //{
            //    var typename = type.FullName;

            //    foreach (FieldInfo field in type.GetFields(BindingFlags.Instance |
            //                                               BindingFlags.Static |
            //                                               BindingFlags.Public |
            //                                               BindingFlags.NonPublic))
            //    {
            //        string data = field.Name + " - " + field.FieldType;
            //    }
            //}
            //Type MyLoadClass = assembly.GetType("HaoClass");
            //object tmp = Activator.CreateInstance(MyLoadClass); 
            //***********************************************************************

            //READ TABLE PROPERTY****************
            //var res = from a in adc.Tables select a;
            //foreach (var c in res)
            //{
            //    var s = "";
            //}
            //************************************

            StringBuilder dc = new StringBuilder(512);

            dc.Append("using Idte.HumanResource.Core.dll;");
            dc.Append("public class HaoClass");
            dc.Append("{");
            dc.Append("public int First_Name { get; set; }");
            dc.Append("public string Last_Name { get; set; }");
            dc.Append("public string Email { get; set; }");
            dc.Append("public MyClass _class { get; set; }");
            dc.Append("}");

            dc.Append("public class MyClass");
            dc.Append("{");
            dc.Append("public int First_Name { get; set; }");
            dc.Append("public string Last_Name { get; set; }");
            dc.Append("public string Email { get; set; }");
            dc.Append("public HaoClass MyHao { get; set; }");
            dc.Append("}");
            CompilerResults compiledResult = CompileScript(dc.ToString());
            if (compiledResult.Errors.HasErrors)
            {
                Console.WriteLine(compiledResult.Errors[0].ErrorText);
                throw new InvalidOperationException("Invalid Expression syntax");
            }

        }
        public static void DisplayCompilerResults(System.CodeDom.Compiler.CompilerResults cr)
        {
            // If errors occurred during compilation, output the compiler output and errors. 
            if (cr.Errors.Count > 0)
            {
                for (int i = 0; i < cr.Output.Count; i++)
                    Console.WriteLine(cr.Output[i]);
                for (int i = 0; i < cr.Errors.Count; i++)
                    Console.WriteLine(i.ToString() + ": " + cr.Errors[i].ToString());

            }
            else
            {
                // Display information about the compiler's exit code and the generated assembly.
                Console.WriteLine("Compiler returned with result code: " + cr.NativeCompilerReturnValue.ToString());
                Console.WriteLine("Generated assembly name: " + cr.CompiledAssembly.FullName);
                if (cr.PathToAssembly == null)
                    Console.WriteLine("The assembly has been generated in memory.");
                else
                    Console.WriteLine("Path to assembly: " + cr.PathToAssembly);

                // Display temporary files information. 
                if (!cr.TempFiles.KeepFiles)
                    Console.WriteLine("Temporary build files were deleted.");
                else
                {
                    Console.WriteLine("Temporary build files were not deleted.");
                    // Display a list of the temporary build files
                    IEnumerator enu = cr.TempFiles.GetEnumerator();
                    for (int i = 0; enu.MoveNext(); i++)
                        Console.WriteLine("TempFile " + i.ToString() + ": " + (string)enu.Current);
                }
            }
        }
        public static CompilerResults CompileScript(string source)
        {
            CompilerParameters parms = new CompilerParameters();
            parms.GenerateExecutable = false;
            parms.GenerateInMemory = false;
            parms.IncludeDebugInformation = false;
            parms.OutputAssembly = "D:\\Cycle.dll";

            CodeDomProvider compiler = CSharpCodeProvider.CreateProvider("CSharp");

            return compiler.CompileAssemblyFromSource(parms, source);


        }

        readonly EFContextProvider<AppDesignContext> _contextProvider =
            new EFContextProvider<AppDesignContext>();

        [HttpGet]
        public void SaveModifiedKey(string KeyName1, string KeyVal1,string KeyName2, string KeyVal2,string KeyName3, string KeyVal3 , string TypeName, string newKey3)
        {
            
            AppDesignContext _context = new AppDesignContext();
            string query = "UPDATE " + TypeName + " SET " + KeyName3 + "= '" + newKey3 +
                "' WHERE " + KeyName1 + " = '" + KeyVal1 + "' AND " +
                            KeyName2 + " = '" + KeyVal2 + "' AND " +
                            KeyName3 + " = '" + KeyVal3 + "'";

            _context.Database.ExecuteSqlCommand(query);
        }


        [HttpGet]
        public string Metadata()
        {
            return _contextProvider.Metadata();
        }

        [HttpPost]
        public SaveResult SaveChanges(JObject saveBundle)
        {
            return _contextProvider.SaveChanges(saveBundle);
        }
        
        [HttpGet]
        public IQueryable<AppTypes> AppTypes()
        {
            return _contextProvider.Context.Set<AppTypes>().Include("Parent").Include("Children").Include("OutsideRelationships").Include("AppLayouts");
        }
        [HttpGet]
        public IQueryable<DomainTypes> DomainTypes()
        {
            return _contextProvider.Context.Set<DomainTypes>().Include("Parent").Include("Children");
        }
        [HttpGet]
        public IQueryable<AppLayout> AppLayouts()
        {
            return _contextProvider.Context.Set<AppLayout>();
        }
        [HttpGet]
        public IQueryable<AppRelation> AppRelations()
        {
            return _contextProvider.Context.Set<AppRelation>();
        }

    }
}
